include std/dll.e
include std/machine.e
include std/convert.e
include qt/debug_utils.e

include core.e  --think core should be including this?
include wrap_helpers.e

constant
	hQt_settings = define_c_func(hEuQt, "qts_settings", {CP,I,P}, P),
	hQt_contains = define_c_func(hEuQt, "qts_contains", {P, CP}, I),
	hQt_remove = define_c_func(hEuQt, "qts_remove", {P, CP}, I),
	hQt_setValue = define_c_func(hEuQt, "qts_setValue", {P,CP,CP}, I),
	hQt_value = define_c_func(hEuQt, "qts_value", {P,CP}, P),
	hQt_beginGroup = define_c_proc(hEuQt, "qts_beginGroup", {P,CP}),
	hQt_endGroup = define_c_proc(hEuQt, "qts_endGroup", {P}),

	hQtTimer = define_c_func(hEuQt, stdcall&"qt_Timer", {P}, P),
	hQtStopTimer = define_c_func(hEuQt, stdcall&"qt_stopTimer", {P}, I),
	hQtStartTimer = define_c_func(hEuQt, stdcall&"qt_startTimer", {P}, I),
	hQtSetIntervalTimer = define_c_func(hEuQt, stdcall&"qt_setIntervalTimer", {P,I}, I),
	
	hQt_Process = define_c_func(hEuQt, "qt_Process", {P}, P),
	hQt_startProcess = define_c_func(hEuQt, "qt_startProcess", {P,CP,CPP}, I),
	hQt_readProcess = define_c_func(hEuQt, "qt_readProcess", {P}, P),
	hQt_killProcess = define_c_func(hEuQt, "qt_killProcess", {P}, I),
	hQt_errorProcess = define_c_func(hEuQt, "qt_errorProcess", {P}, I),
	hQt_errorStringProcess = define_c_func(hEuQt, "qt_errorStringProcess", {P}, CP),
	hQt_closeProcess = define_c_func(hEuQt, "qt_closeProcess", {P}, I),
	$

--****
-- everything is experimental and or not yet fully implemented
--
-- makes available various Qt utilitiy classes and functions.
-- *compression zip gz via zlib or probably 7zip at some point.
-- *clipboard functions
--  *drag & drop inter widget and between applications
-- * QSettings selectable for ini anywhere or registry on windows
-- * QProcess for running programs
-- * QTimer
--
-- for QSql and QXml include those routines wrapped in qtSql.e and qtXml.e
--
--<<LEVELTOC depth=2>>


--****
--=== QSettings
--The table below summarizes the default values:

-- ||Platform ||Format ||Scope ||Path ||
-- |Windows  |IniFormat  |UserScope  |%APPDATA%  
-- 	SystemScope %COMMON_APPDATA%  |
-- |Unix NativeFormat,  |IniFormat  |UserScope  |$HOME/.config 
-- 	SystemScope /etc/xdg  |
-- |Qt for Embedded Linux  |NativeFormat,  |IniFormat  |UserScope $HOME/Settings 
-- 	SystemScope /etc/xdg  |
-- |Mac OS X  |IniFormat  |UserScope  |$HOME/.config 
--	SystemScope /etc/xdg  |
--
--The default UserScope paths on Unix and Mac OS X ($HOME/.config or $HOME/Settings) can be overridden by the user by setting the XDG_CONFIG_HOME environment variable. The default SystemScope paths on Unix and Mac OS X (/etc/xdg) can be overridden when building the Qt library using the configure script's --sysconfdir flag (see QLibraryInfo for details).



--**
--little bit complicated because Qt routines are so overloaded.
--for now, keys can only be string values.
--
--may need seperate functions or a flag to say which is being called
-- ##settings("some.ini")## would be a basic usage and semi portable.
--it may be possible to parse flags to guess but not in every case.
--
--Qt does not lock the file while under usage. sync() is called after all
--the functions so it shouldn't be a problem editing from another app,
--may not preserve order and strips all comments from file on update
--this seems like a Qt bug,.
--
-- Qt may have a watcher for changed files?
--
--you do have to escape backslashes used in the ini, so that would mean quad backslashes in strings.
-- see the docs, @ might be another character requireing escaping.
-- QQQ Note that the backslash character is used by QSettings to separate subkeys. 
--As a result, you cannot read or write windows registry entries that contain slashes or backslashes;
--you should use a native windows API if you need to do so.QQQ
--needs more testing, that could mean unescaped slashes or backslashes?
--entering filenames and paths into the registry is about half the reason for accessing it!
--
--just calling it doesn't create a zero len file apparently?
--
--still need remove group and more error checking.
--
-- **caution**: on windows you can also set and get registry values
-- by using  ##QSettings_NativeFormat##, the Qt defaut on windows
-- instead of ##QSettings_IniFormat## the euqt default for settings. 
-- the same caution applies to inadvertent changes to any system wide ini file.

public function settings(object loc, object fl=QSettings_IniFormat, object parent=0)
	atom pl, pf
	if sequence(loc) then pl=allocate_string(loc,1)
	else pl=loc
	end if
	if sequence(fl) then pf=allocate_string(fl,1)
	else pf=fl
	end if

	    --is it safe to or_all fl if a sequence?
	    --not sure yet the various usage

	return c_func(hQt_settings, {pl, pf, parent})
end function


--**
-- set key to val in setting. val is always a string for now.
--setting is the atom returned from settings.
--
-- return value is the same object passed to it. this is useful when
-- setting up default values also contained in local variables.
--
-- **caution**: on windows you can also set and get registry values.

public function setValue(atom setting, object key, object fl)
	atom pl, pf
	if sequence(key) then pl=allocate_string(key,1)
	else pl=key
	end if
	if sequence(fl) then pf=allocate_string(fl,1)
	else pf=allocate_string(itoa(fl),1)
	end if
	c_func(hQt_setValue, {setting, pl, pf})
	return fl
end function


--**
-- return string val at key in setting.
-- val is always a string for now.
--setting is the atom returned from settings.
-- might it be useful to have a way to pass in a default value?
--would have to check if key not exist then set or something

public function value(atom setting, object key)
	atom pl
	if sequence(key) then pl=allocate_string(key,1)
	else pl=key
	end if
	    
	return peek_string(c_func(hQt_value, {setting, pl}) )
end function

--**
-- remove the group and any keys
-- **caution**: this could cause trouble to inadvertently delete whole registry groups.
public function removeGroup(atom setting, sequence group)
	atom pl
	pl=allocate_string(group,1)
	    
	return c_func(hQt_remove, {setting, pl})
end function


--**
-- true/false 1/0 is key in current group
public function contains(atom setting, sequence key)
	atom pl
	pl=allocate_string(key,1)
	    
	return c_func(hQt_contains, {setting, pl})
end function


--**
-- start group, may start another group or a key if that group exists
public procedure beginGroup(atom setting, object group)
	atom pg
	if sequence(group) then pg=allocate_string(group,1)
	else pg=group
	end if
	c_proc(hQt_beginGroup, {setting, pg})
end procedure

--**
-- end current group and return to previous group
public procedure endGroup(atom setting)
	c_proc(hQt_endGroup, {setting})
end procedure


--need a listGroups  listK



--****
--=== QProcess
--highly experimental, not nearly wrapped enough to be functional
--
-- opens a process that can be read or written to. in the current process or detached.
--
--will be able to read stdout or stderr which current euphoria has a problem with.
--and euphoria system() mangles the arguments a little and is limited in what
--return values it can return from something like a batch file on windows.
--

--**
-- return a process pointer, you should probably destroy if it will be reused
--to avoid leaking memory held by the process. normally on program end
--all widget and process used memory will be returned to the system.
--
public function Process(atom parent=qApp)  --0/qApp ?
	return c_func(hQt_Process, {parent})
end function

--**
--pros is the atom returned from Process
--
--args need to be an array, can probably split on a coma.
--
--you can omit args and or include arguments to the program combined.
--Note that, on Windows, quotes need to be both escaped and quoted. 
-- to ensure that "My Documents" is used as the argument to the dir executable:
-- startProcess(pros, "dir \"\"\"My Documents\"\"\"")
--the raw string version would look a little less busy.
--there may also be a problem with the example taken from the Qt docs,
-- filed a bug report, earlier in the docs it mentions window command like dir
--are actually contained in the %COMSPEC% command.com or cmd.exe
--and won't work from a process, the actual example should be something liike: 
-- startProcess(pros, "cmd dir \"\"\"My Documents\"\"\"")
--will simplify the example once process actually works.

public function startProcess(atom pros, object prog, object args={{}})
	atom pprog, parg
	if sequence(prog) then pprog=allocate_string(prog,1)
	else pprog=prog
	end if
	
	if sequence(args) then parg=allocate_string_pointer_array(args,1)
	else parg=args
	end if
	--char **=0 not working well for default args
	return c_func(hQt_startProcess, {pros, pprog, parg})
end function

-- Parameters:
--   # ##pros##:an atom return from Process()
--	 
-- Returns:
--   a string sequence containing the stdout of the process
-- Note: if the process hasn't actually started it could hang
-- very little error checking is done at this point
-- would be advisable to connect the start() signal and finished() signal
-- and only attempt to read from inside those callbacks once activated.
-- Example 1:
-- <eucode>
-- </eucode>

public function readProcess(atom pros)
    atom ret = c_func(hQt_readProcess, {pros})
    if ret>0 then
	return peek_string(ret)
    end if
    return ""
end function

public function errorStringProcess(atom pros)
    atom ret = c_func(hQt_errorStringProcess, {pros})
    if ret>0 then
	return peek_string(ret)
    else
	return ""
    end if
end function

public function killProcess(atom pros)
	return c_func(hQt_killProcess, {pros})
end function

public function closeProcess(atom pros)
	return c_func(hQt_closeProcess, {pros})
end function


--****
--=== QTimers

--** 
-- create a timer for the app, not sure widgets can parent timers yet
-- calls set interval if n>0
-- return 0 if invalid timer or couldn't create
--
--you can set the singleShot  property to have the timer only fir
public function Timer(atom app=qApp, integer n=0)
	atom t=c_func(hQtTimer, {app})
	if t and n then 
	    atom x=setIntervalTimer(t, n) 
	end if
	return t
end function

--** 
-- return true if valid timer
--might be a slight delay unless you stopTimers when quiting??
public function stopTimer(atom t)
	return c_func(hQtStopTimer, {t})
end function

--** 
-- t is atom returned from Timer.
--calls set interval if n>0
-- return true if valid timer
public function startTimer(atom t, integer n=0)
	atom ts=c_func(hQtStartTimer, {t})
	if t and n then 
	    atom x=setIntervalTimer(t, n) 
	end if
	return ts
end function

--** 
--in microseconds, don't expect realtime under 100, probably more.
-- 4000 is 4 seconds more or less depending on system and other system activity.
--see the Qt docs.
-- return true if valid timer

public function setIntervalTimer(atom t, integer n)
	return c_func(hQtSetIntervalTimer, {t, n})
end function

--****
--=== QCompression



--****
--=== QNetwork
--will probably have it's own file

--****
--=== Phonon
--will probably have it's own file
--~ AudioOutput ( QObject * parent = 0 ) 
--~ //~ muted : bool 
--~ //~ name : QString 
--~ //~ outputDevice : 
--~ //~ volumeDecibel : qreal  
  --~ //~ volume : qreal 
	--~ qDebug() << QSound::isAvailable() << "QSound::isAvailable";
	--~ //~ QString user(env.section("GIT_AUTHOR_NAME", 1).section(",", 0, 0).section("=", 1).trimmed());
	--~ qDebug() << BackendCapabilities::availableAudioDevices().join(",");


--****
--=== QWebKit
--will probably have it's own file

